﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
//using Expression = Microsoft.Expression.Interactivity;
using System.Windows.Interactivity;
using System.Linq;
using System.Windows.Data;
using System.Collections.Generic;
using System.Reflection;
//using Microsoft.Expression.Interactions;
using Microsoft.Expression;
using Microsoft.Expression.Interactivity;
using Microsoft.Expression.Interactivity.Layout;


namespace MikesDragDropBits
{
  public class DraggableBehavior : Behavior<MouseDragElementBehavior>
  {
    public DraggableBehavior()
    {
    }
    public string PropertyPath { get; set; }

    protected override void OnAttached()
    {
      base.OnAttached();
      //MouseDragElementBehavior e = new MouseDragElementBehavior();
        
      //(AssociatedObject as UIElement).MouseRightButtonDown += new MouseButtonEventHandler(Element_MouseRightButtonDown);
      //(AssociatedObject as UIElement).MouseRightButtonUp += new MouseButtonEventHandler(Element_MouseRightButtonUp);
    }

    protected override void OnDetaching()
    {
      base.OnDetaching();
        		//AssociatedObject.MouseLeftButtonDown -= Element_MouseRightButtonDown;
        		//AssociatedObject.MouseLeftButtonUp -= Element_MouseRightButtonUp;
    }

void Element_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    e.Handled = true;
}
 
void Element_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
    //MouseLeftButtonUp();
}

  }
}


/*
namespace MikesDragDropBits
{
  public class DraggableBehavior : Behavior<FrameworkElement>
  {
    public DraggableBehavior()
    {
    }
    public string PropertyPath { get; set; }

    protected override void OnAttached()
    {
      base.OnAttached();
      this.AssociatedObject.MouseLeftButtonDown += OnMouseDown;
      this.AssociatedObject.MouseLeftButtonUp += OnMouseUp;
      this.AssociatedObject.MouseMove += OnMouseMove;     
    }
    protected override void OnDetaching()
    {
      base.OnDetaching();
      this.AssociatedObject.MouseLeftButtonDown -= OnMouseDown;
      this.AssociatedObject.MouseLeftButtonUp -= OnMouseUp;
      this.AssociatedObject.MouseMove -= OnMouseMove;
    }
    void OnMouseMove(object sender, MouseEventArgs e)
    {
      if (isDragging)
      {
        if (injectedUI == null)
        {
          Point localPoint = e.GetPosition(this.AssociatedObject);
          Point globalPoint = e.GetPosition(Application.Current.RootVisual);
          capturePoint = globalPoint;
          globalPoint.X -= localPoint.X;
          globalPoint.Y -= localPoint.Y;
          injectedUI = new DragDropUIInjector(this.AssociatedObject, globalPoint);
          injectedUI.InjectUI();
        }
        else
        {
          Point currentPoint = e.GetPosition(Application.Current.RootVisual);
          injectedUI.ApplyDelta(currentPoint.X - capturePoint.X,
            currentPoint.Y - capturePoint.Y);
          capturePoint = currentPoint;
        }
      }
    }
    void OnMouseUp(object sender, MouseButtonEventArgs e)
    {
      this.AssociatedObject.ReleaseMouseCapture();
      isDragging = false;

      if (injectedUI != null)
      {
        injectedUI.RemoveUI();
        injectedUI = null;
        HitTestAndInvokeTriggers(e.GetPosition(Application.Current.RootVisual));
      }
    }
    void HitTestAndInvokeTriggers(Point p)
    {
      object dataObject = GetDataObject();

      foreach (DropTrigger trigger in GetDropTriggersOfFirstElement(p))
      {
        trigger.InvokeActions(dataObject);
      }
    }
    object GetDataObject()
    {
      object dataObject = this.AssociatedObject;

      if (!string.IsNullOrEmpty(this.PropertyPath))
      {
        dataObject = null;

        Type t = this.AssociatedObject.GetType();

        PropertyInfo propertyInfo = t.GetProperty(this.PropertyPath,
          BindingFlags.Public | BindingFlags.Instance);

        if (propertyInfo != null)
        {
          dataObject = propertyInfo.GetValue(this.AssociatedObject, null);
        }
      }
      return (dataObject);
    }
    static IEnumerable<DropTrigger> GetDropTriggersOfFirstElement(Point p)
    {
      var elements = VisualTreeHelper.FindElementsInHostCoordinates(p,
        Application.Current.RootVisual);  

      if (elements != null)
      {
        foreach (var item in elements)
        {
          //var triggers = System.Windows.Interactivity.Interaction.ge GetTriggers(item);
/*
var triggers = System.Windows.Interactivity.Interaction.GetTriggers(item);

          if ((triggers != null) && (triggers.Count > 0))
          {
            foreach (System.Windows.Interactivity.TriggerBase trigger in triggers)
            {
              if (trigger is DropTrigger)
              {
                yield return (DropTrigger)trigger;                
              }
            }
            break;
          }
        }
      }
    }
    void OnMouseDown(object sender, MouseButtonEventArgs e)
    {
      if (!isDragging)
      {
        isDragging = true;
        this.AssociatedObject.CaptureMouse();
      }
    }
    bool isDragging;
    DragDropUIInjector injectedUI;
    Point capturePoint;
  }
}
*/












/*
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity;
using Microsoft.Expression.Interactions;

namespace MouseRightDragElementBehavior
{
	
public class MouseRighButtontDragElementBehavior : MouseDragElementBehavior
{
    public void MouseRightButtonDragElementBehavior()
    {
        
		//AssociatedObject.AddHandler(FrameworkElement.MouseRightButtonDownEvent, new MouseButtonEventHandler(child_MouseRightButtonDown),true);
		this.DragBegun += new MouseEventHandler(DragBehvaior_DragBegun);
    }

    void DragBehvaior_DragBegun(object sender, MouseEventArgs e)
    {
        var element = this.AssociatedObject as UIElement;
        // Calculate the correct ZIndex here.
        Canvas.SetZIndex(element, 100);
    }
}
}

*/

/*
    public class MouseRightDragElementBehavior : Behavior<Panel>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
        }
        protected override void OnDetaching()
        {
            base.OnDetaching();
                //child.RemoveHandler(FrameworkElement.MouseRightButtonDownEvent, new MouseButtonEventHandler(child_MouseRightButtonDown));
				AssociatedObject.MouseMove -= Element_MouseMove;
        		AssociatedObject.MouseLeftButtonDown -= Element_MouseRightButtonDown;
        		AssociatedObject.MouseLeftButtonUp -= Element_MouseRightButtonUp;
			
			foreach (var child in AssociatedObject.Children)
            {
				child.MouseMove -= Element_MouseMove;
        		child.MouseLeftButtonDown -= Element_MouseRightButtonDown;
        		child.MouseLeftButtonUp -= Element_MouseRightButtonUp;
			}
        }
		
bool isDragDropInEffect = false;
Point pos;

        void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
        /*
			AssociatedObject.AddHandler(FrameworkElement.MouseRightButtonDownEvent, new MouseButtonEventHandler(child_MouseRightButtonDown),true);
			AssociatedObject.AddHandler(FrameworkElement.MouseRightButtonUpEvent, new MouseButtonEventHandler(child_MouseRightButtonUp),true);
			AssociatedObject.AddHandler(FrameworkElement.MouseRightButtonDownEvent, new MouseButtonEventHandler(child_MouseRightButtonDown),true);
			*/
/*				AssociatedObject.MouseMove += new MouseEventHandler(Element_MouseMove);
        		AssociatedObject.MouseRightButtonDown += new MouseButtonEventHandler(Element_MouseRightButtonDown);
        		AssociatedObject.MouseRightButtonUp += new MouseButtonEventHandler(Element_MouseRightButtonUp);
			
			foreach (var child in AssociatedObject.Children)
            {
				child.MouseMove += new MouseEventHandler(Element_MouseMove);
        		child.MouseRightButtonDown += new MouseButtonEventHandler(Element_MouseRightButtonDown);
        		child.MouseRightButtonUp += new MouseButtonEventHandler(Element_MouseRightButtonUp);
			}
        }
/*		
void Element_MouseMove(object sender, MouseEventArgs e)
{
    if (isDragDropInEffect)
    {
        FrameworkElement currEle = sender as FrameworkElement;
        // Retrieving the item's current x and y position
        double xPos = e.GetPosition(null).X - pos.X;
        double yPos = e.GetPosition(null).Y - pos.Y;
 
        // Re-position Element
        currEle.SetValue(Canvas.TopProperty, yPos + (double)currEle.GetValue(Canvas.TopProperty));
        currEle.SetValue(Canvas.LeftProperty, xPos + (double)currEle.GetValue(Canvas.LeftProperty));
 
        // Reset the new position value
        pos = e.GetPosition(null);
    }
}

void Element_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    FrameworkElement fEle = sender as FrameworkElement;
    isDragDropInEffect = true;
    // x and y coords of mouse pointer position
    pos = e.GetPosition(null);  
    // Enable mouse capture on element
    fEle.CaptureMouse();
    // Set the cursor to 'Hand' when mouse pointer is over element
    fEle.Cursor = Cursors.Hand;
	           e.Handled = true;
 
}
 
void Element_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
    if (isDragDropInEffect)
    {
        FrameworkElement ele = sender as FrameworkElement;
        isDragDropInEffect = false;
        // Removes Mouse Capture from Element being dragged
        ele.ReleaseMouseCapture();
    }
}
    }
}
*/


/*
namespace Interactivity.Behaviors
{
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    using System.Windows.Media;

    public class ItemsControlMouseDragElementBehavior : Behavior<ItemsControl>
    {
        #region Fields

        private bool isDragging;
        private bool isMouseDown;
        private FrameworkElement itemContainer;
        private Point lastPoint;
        private FrameworkElement parent;
        private bool settingPosition;

        #endregion Fields

        #region Properties

        private FrameworkElement ParentElement
        {
            get
            {
                return parent;
            }
        }

        #endregion Properties

        #region Methods

        public static object GetDataObjectFromItemsControl(ItemsControl itemsControl, Point p)
        {
            UIElement element = itemsControl.InputHitTest(p) as UIElement;
            while (element != null)
            {
                if (element == itemsControl)
                    return null;

                object data = itemsControl.ItemContainerGenerator.ItemFromContainer(element);
                if (data != DependencyProperty.UnsetValue)
                {
                    return data;
                }
                else
                {
                    element = VisualTreeHelper.GetParent(element) as UIElement;
                }
            }
            return null;
        }

        public static FrameworkElement GetItemContainerFromPoint(ItemsControl itemsControl, Point p)
        {
            FrameworkElement element = itemsControl.InputHitTest(p) as FrameworkElement;
            while (element != null)
            {
                if (element == itemsControl)
                    return null;

                object data = itemsControl.ItemContainerGenerator.ItemFromContainer(element);
                if (data != DependencyProperty.UnsetValue)
                {
                    return element;
                }
                else
                {
                    element = VisualTreeHelper.GetParent(element) as FrameworkElement;
                }
            }
            return null;
        }

        internal static Rect GetLayoutRect(FrameworkElement element)
        {
            double actualWidth = element.ActualWidth;
            double actualHeight = element.ActualHeight;
            if ((element is Image) || (element is MediaElement))
            {
                if (element.Parent.GetType() == typeof(Canvas))
                {
                    actualWidth = double.IsNaN(element.Width) ? actualWidth : element.Width;
                    actualHeight = double.IsNaN(element.Height) ? actualHeight : element.Height;
                }
                else
                {
                    actualWidth = element.RenderSize.Width;
                    actualHeight = element.RenderSize.Height;
                }
            }
            actualWidth = (element.Visibility == Visibility.Collapsed) ? 0.0 : actualWidth;
            actualHeight = (element.Visibility == Visibility.Collapsed) ? 0.0 : actualHeight;
            Thickness margin = element.Margin;
            Rect layoutSlot = LayoutInformation.GetLayoutSlot(element);
            double x = 0.0;
            double y = 0.0;
            switch (element.HorizontalAlignment)
            {
                case HorizontalAlignment.Left:
                    x = layoutSlot.Left + margin.Left;
                    break;

                case HorizontalAlignment.Center:
                    x = ((((layoutSlot.Left + margin.Left) + layoutSlot.Right) - margin.Right) / 2.0) - (actualWidth / 2.0);
                    break;

                case HorizontalAlignment.Right:
                    x = (layoutSlot.Right - margin.Right) - actualWidth;
                    break;

                case HorizontalAlignment.Stretch:
                    x = Math.Max((double)(layoutSlot.Left + margin.Left), (double)(((((layoutSlot.Left + margin.Left) + layoutSlot.Right) - margin.Right) / 2.0) - (actualWidth / 2.0)));
                    break;
            }
            switch (element.VerticalAlignment)
            {
                case VerticalAlignment.Top:
                    y = layoutSlot.Top + margin.Top;
                    break;

                case VerticalAlignment.Center:
                    y = ((((layoutSlot.Top + margin.Top) + layoutSlot.Bottom) - margin.Bottom) / 2.0) - (actualHeight / 2.0);
                    break;

                case VerticalAlignment.Bottom:
                    y = (layoutSlot.Bottom - margin.Bottom) - actualHeight;
                    break;

                case VerticalAlignment.Stretch:
                    y = Math.Max((double)(layoutSlot.Top + margin.Top), (double)(((((layoutSlot.Top + margin.Top) + layoutSlot.Bottom) - margin.Bottom) / 2.0) - (actualHeight / 2.0)));
                    break;
            }
            return new Rect(x, y, actualWidth, actualHeight);
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObjectPreviewMouseLeftButtonDown;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObjectPreviewMouseLeftButtonDown;
        }

        private static Point GetTransformOffset(GeneralTransform transform)
        {
            return transform.Transform(new Point(0.0, 0.0));
        }


        private static Point TransformAsVector(GeneralTransform transform, double x, double y)
        {
            Point point = transform.Transform(new Point(0.0, 0.0));
            Point point2 = transform.Transform(new Point(x, y));
            return new Point(point2.X - point.X, point2.Y - point.Y);
        }

        private void ApplyTranslation(double x, double y)
        {
            if (this.ParentElement == null) return;
            Point point = TransformAsVector(this.itemContainer.TransformToVisual(this.ParentElement), x, y);
            x = point.X;
            y = point.Y;
            this.ApplyTranslationTransform(x, y);
        }

        private void ApplyTranslationTransform(double x, double y)
        {
            Transform renderTransform = itemContainer.RenderTransform;
            TransformGroup group = renderTransform as TransformGroup;
            MatrixTransform transform2 = renderTransform as MatrixTransform;
            TranslateTransform transform3 = renderTransform as TranslateTransform;
            if (transform3 == null)
            {
                if (group != null)
                {
                    if (group.Children.Count > 0)
                    {
                        transform3 = group.Children[group.Children.Count - 1] as TranslateTransform;
                    }
                    if (transform3 == null)
                    {
                        transform3 = new TranslateTransform();
                        group.Children.Add(transform3);
                    }
                }
                else
                {
                    if (transform2 != null)
                    {
                        Matrix matrix = transform2.Matrix;
                        matrix.OffsetX += x;
                        matrix.OffsetY += y;
                        MatrixTransform transform4 = new MatrixTransform
                                                         {
                                                             Matrix = matrix
                                                         };
                        itemContainer.RenderTransform = transform4;
                        return;
                    }
                    TransformGroup group2 = new TransformGroup();
                    transform3 = new TranslateTransform();
                    if (renderTransform != null)
                    {
                        group2.Children.Add(renderTransform);
                    }
                    group2.Children.Add(transform3);
                    itemContainer.RenderTransform = group2;
                }
            }
            transform3.X += x;
            transform3.Y += y;
        }

        private void AssociatedObjectPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!(Keyboard.IsKeyDown(Key.RightCtrl) || Keyboard.IsKeyDown(Key.LeftCtrl))) return;

            ItemsControl itemsControl = (ItemsControl)sender;
            Point p = e.GetPosition(itemsControl);
            itemContainer = GetItemContainerFromPoint(itemsControl, p);
            if (itemContainer != null)
            {
                isMouseDown = true;
                lastPoint = p;
                this.parent = VisualTreeHelper.GetParent(itemContainer) as FrameworkElement;
                this.AssociatedObject.CaptureMouse();
                this.AssociatedObject.PreviewMouseMove += AssociatedObjectPreviewMouseMove;
                this.AssociatedObject.PreviewMouseLeftButtonUp += AssociatedObjectPreviewMouseLeftButtonUp;
            }
        }

        private void AssociatedObjectPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            isMouseDown = false;
            isDragging = false;
            this.AssociatedObject.ReleaseMouseCapture();
            this.AssociatedObject.PreviewMouseMove -= AssociatedObjectPreviewMouseMove;
            this.AssociatedObject.PreviewMouseLeftButtonUp -= AssociatedObjectPreviewMouseLeftButtonUp;
        }

        private void AssociatedObjectPreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (isMouseDown)
            {
                ItemsControl itemsControl = (ItemsControl)sender;
                Point position = e.GetPosition(itemsControl);
                double x = position.X - this.lastPoint.X;
                double y = position.Y - this.lastPoint.Y;
                this.lastPoint = position;

                if ((isDragging == false) &&
                    (Math.Abs(x) > SystemParameters.MinimumHorizontalDragDistance) ||
                    (Math.Abs(y) > SystemParameters.MinimumVerticalDragDistance))
                {
                    isDragging = true;
                }

                if (isDragging)
                {
                    this.settingPosition = true;
                    this.ApplyTranslation(x, y);
                    this.UpdatePosition();
                    this.settingPosition = false;
                }
            }
        }

        private void UpdatePosition()
        {
            Point transformOffset = GetTransformOffset(itemContainer.TransformToVisual(this.AssociatedObject));
            //TODO: add support for items to read their current X Y positions using attached properties 
            //this.X = transformOffset.X;
            //this.Y = transformOffset.Y;
        }

        #endregion Methods
    }
}
	*/